#include "mainwindow.h"
struct  serial_buf_t serial_recv_buf;//串口接收buf结构。

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{

    creatMenu();
    creatAction();

    creatMainPage();
    creatSysClock();
    general_op();
}

MainWindow::~MainWindow()
{

}
void MainWindow::creatMenu()
{
    menu_file = menuBar()->addMenu("File");
    menu_file->addSeparator();
    menu_set = menuBar()->addMenu("Set");
    menu_set->addSeparator();
    menu_help = menuBar()->addMenu("Help");
    menu_help->addSeparator();

    menu_test = menuBar()->addMenu("Test");

}
void MainWindow::creatAction()
{
    newAct = new  QAction("new");
    menu_file->addAction(newAct);
    openAct = new   QAction("open");
    menu_file->addAction(openAct);
    saveAct = new  QAction("save");
    menu_file->addAction(saveAct);
    printAct = new QAction("print");
    menu_file->addAction(printAct);

    aboutAct = new QAction("about");
    menu_help->addAction(aboutAct);
    connect(aboutAct,SIGNAL( triggered()),this,SLOT(createAbout()));

    menu_act = new QAction("Test_serial");
    menu_test ->addAction(menu_act);
   setAction  = new     QAction("Set");
   menu_set ->addAction(setAction);
    connect(setAction,SIGNAL( triggered()),this,SLOT(slot_create_set()));
}
void MainWindow::createAbout()
{
    qDebug()<<"receive about signal";
    about  = new qtabout();
}
void MainWindow::creatMainPage()
{

    widget  = new QWidget;
    configLayout = new QVBoxLayout();
    configLayout_serial  = new QGridLayout();
    mainLayout = new QHBoxLayout();

    frameBrowser = new QTextBrowser();

    sysconfig = new QVBoxLayout();

    serial_port = new QLabel("端口");
    serial_baud= new QLabel("波特率");
    serial_parity= new QLabel("校验位");
    serial_data= new QLabel("数据位");
   serial_stop= new QLabel("停止位");
    serial_port_com = new QComboBox(); //com口
    serial_port_com->addItem("COM1");
    serial_port_com->addItem("COM2");
    serial_port_com->addItem("COM3");
    serial_port_com->addItem("COM4");
    serial_port_com->addItem("COM5");
    serial_port_com->addItem("COM6");
   serial_baud_com= new QComboBox();  //波特率
   serial_baud_com->addItem("2400");
   serial_baud_com->addItem("4800");
   serial_baud_com->addItem("9600");
   serial_baud_com->addItem("115200");
    serial_parity_com= new QComboBox(); //校验位
    serial_parity_com -> addItem("E");
    serial_parity_com -> addItem("O");
    serial_parity_com -> addItem("N");
  serial_data_com= new QComboBox();  //数据位
    serial_data_com->addItem("8");
   serial_stop_com= new QComboBox();  //停止位
    serial_stop_com ->addItem("1");
   serial_open = new QPushButton("打开");
   serial_close = new QPushButton("关闭");
   systime = new QLabel();
   configLayout_serial->addWidget(serial_port,0,0);
   configLayout_serial->addWidget(serial_baud,1,0);
   configLayout_serial->addWidget(serial_parity,2,0);
   configLayout_serial->addWidget(serial_data,3,0);
   configLayout_serial->addWidget(serial_stop,4,0);
   configLayout_serial->addWidget(serial_port_com,0,1);
   configLayout_serial->addWidget(serial_baud_com,1,1);
   configLayout_serial->addWidget(serial_parity_com,2,1);
   configLayout_serial->addWidget(serial_data_com,3,1);
   configLayout_serial->addWidget(serial_stop_com,4,1);
   configLayout_serial->addWidget(serial_open,5,0);
    configLayout_serial->addWidget(serial_close,5,1);
   configLayout->addLayout(configLayout_serial);
    configLayout->addStretch();  //这个弹簧要加到layout上。
    //加上系统时间等设置。
    systimer = new QTime();
    QString str = QString("系统时间是 ");
    str.append(systimer->currentTime().toString());
    systime->setText(str);

    frame_text_RxTx = new QGridLayout();  //收发报文显示 layout
     sendFrameEdit = new  QTextEdit();  //发送edit
     sendokbutton  =  new QPushButton();//发送确认按钮。
     serial_intput_state = new QLabel();   //输入数据正确性。
     serial_intput_state->setText("input state:");
     sendokbutton->setText("发送");
    frame_text_RxTx->addWidget(frameBrowser,0,0,1,2);
    frame_text_RxTx->addWidget(sendFrameEdit,1,0,2,1);
     frame_text_RxTx->addWidget(serial_intput_state ,1,1,1,1);
    frame_text_RxTx->addWidget(sendokbutton ,2,1,1,1);

    frame_text_RxTx->setRowStretch(0,3);//设置行的比例，比较好用。
    frame_text_RxTx->setRowStretch(1,1);
    frame_text_RxTx->setRowStretch(2,1);
    configLayout->addWidget(systime);
    mainLayout->addLayout(configLayout);
    mainLayout->addLayout(frame_text_RxTx);
    setLayout(mainLayout);
    widget->setLayout(mainLayout);
 /*
     * QMainWindow并没有setLayout()函数，因此不能使用setLayout()函数来设置layout，需要使用间接的方法。
需要做的只是先定义一个QWidget对象，然后使用QMainWindow::setCentralWidget()函数来将该QWidget对象设置为Central Widget，然后使用该QWidget对象的setLayout()函数，就可以了，不过后续对象都要被添加到该QWidget对象下的layout中。
QMainWindow为什么会有这样奇怪的特性呢，原因是这样的：QMainWindow类实际上有一个默认的layout，示意如下：
————————————————
版权声明：本文为CSDN博主「imred」的原创文章，遵循CC 4.0 BY-SA版权协议，转载请附上原文出处链接及本声明。
原文链接：https://blog.csdn.net/imred/article/details/54387583
*/
   setCentralWidget(widget);  //需要用个widget来接管。

   //设置串口设置的信号和槽。
   connect(serial_open,SIGNAL(clicked()),this,SLOT(slot_serial_open()));
   connect(serial_close,SIGNAL(clicked()),this,SLOT(slot_serial_close()));

    serial = new  QSerialPort();  //实例化串口类一个对象


}
void   MainWindow::creatSysClock()
{
    sysclock = new QTimer();
    connect(sysclock, SIGNAL( timeout()), this, SLOT(updatesystime()));
    sysclock->start(1000);

    serial_clock = new QTimer();
    connect(serial_clock, SIGNAL( timeout()), this, SLOT(slot_serial_clock()));
    serial_clock->start(50);
}
 void  MainWindow::updatesystime()
 {
     //加上系统时间等设置。
     QString str = QString("系统时间是 ");
     str.append(systimer->currentTime().toString());
     systime->setText(str);
 }
void MainWindow::slot_serial_open()
{
   /*
    qDebug()<< serial_port_com->currentText() <<serial_baud_com->currentText()<<\
              serial_parity_com->currentText()<< serial_data_com->currentText()<<\
              serial_stop_com->currentText() ;
     */
    serial->setPortName(serial_port_com->currentText());
    serial->setBaudRate(serial_baud_com->currentText().toInt());
    switch (serial_data_com->currentText().toInt()) {
        case '8':
        serial->setDataBits(QSerialPort::Data8);
        break;
    }
    switch (serial_parity_com->currentText().toInt()) {
        case 'E':
        serial->setParity(QSerialPort::EvenParity);
        break;
        case 'O':
            serial->setParity(QSerialPort::OddParity);
        break;
    case 'N':
        serial->setParity(QSerialPort::NoParity);
    break;
    }
    switch (serial_stop_com->currentText().toInt()) {
        case '1':
        serial->setStopBits(QSerialPort::OneStop);
        break;
    }
   serial->setFlowControl(QSerialPort::NoFlowControl);
  if (serial->open(QIODevice::ReadWrite))   //如果串口打开成功。
  {
    serial_open->setEnabled(0);
    serial_port_com ->setEnabled(0);
    serial_baud_com->setEnabled(0);
    serial_parity_com->setEnabled(0);
    serial_data_com->setEnabled(0);
   serial_stop_com->setEnabled(0);
    serial_close->setEnabled(1);
    connect(serial,SIGNAL(readyRead()),this,SLOT(serial_read())); //关联串口的数据可读的信号。
  }
}
void MainWindow::slot_serial_close()
{
    serial->close();
    serial_close->setEnabled(0);
    serial_port_com ->setEnabled(1);
    serial_baud_com->setEnabled(1);
    serial_parity_com->setEnabled(1);
    serial_data_com->setEnabled(1);
    serial_stop_com->setEnabled(1);
    serial_open->setEnabled(1);
}
/*
 * 普通但必要的操作。
*/
void  MainWindow::general_op()
{
    connect(sendokbutton,SIGNAL(clicked()),this,SLOT(slot_sendokbutton()));
    //串口初始化
   serial_recv_buf.head=0;
   serial_recv_buf.tail =0;
   memset(serial_recv_buf.data,0,SERIAL_BUF_LEN);
   protocol_thread = new protocol();  //这里可能需要重新运行qmake
   protocol_thread->start();
}
void MainWindow::serial_read()
{
    char   tmpData[2048];
    qint64    read_ret;
    read_ret = serial->read(tmpData,2048);

    for(int i=0;i<read_ret;i++)
    {
        if( serial_recv_buf.tail== serial_recv_buf.head ) //刚开始为0的时候
         {
               qDebug()<<"first receive";
               serial_recv_buf.data[ serial_recv_buf.tail] = tmpData[i];
               serial_recv_buf.tail++;
               continue;
        }
        if((serial_recv_buf.tail +1) %SERIAL_BUF_LEN != serial_recv_buf.head)
        {
            serial_recv_buf.data[(serial_recv_buf.tail ) %SERIAL_BUF_LEN] = tmpData[i];
            serial_recv_buf.tail = (serial_recv_buf.tail+1)%SERIAL_BUF_LEN;
        }
        else {
            qDebug()<<"serial buffer is full";
        }
    }
    QString  str;
    for(int i=0;i<read_ret;i++)
    {
        str.append(QString::number(tmpData[i],16));  //将一个数据转换成16进制的字符串。
        str.append(' ');
    }
    frameBrowser->append(str);
}
void MainWindow::serial_write(const char * data)
{
    serial->write(data);
}
void  MainWindow::slot_sendokbutton()
{
    QByteArray ba;
    bool  Flag =false;
    int ret;
    QString  str = sendFrameEdit->toPlainText();
    ba = str.toLatin1();
    char *pdata = ba.data();
    int sendpos=0;
    memset(serial_send_buf,0,2048);

    while ((*(pdata) !='\0') ) {
         Flag =false;
        while  ((*(pdata) != ' ') &&(*(pdata) !='\0')) {
            ret = common.Hex2Binary((INT8U*)pdata,2,(INT8U*)(serial_send_buf+sendpos));
            if(ret == -1)
            {
                qDebug()<<"input is not illegal";
                serial_intput_state->setText("input state:Wrong!");
                return;
            }
            sendpos++;
            pdata+=2;
             Flag =true;
        }
        if(!Flag)
        {
              pdata++;
        }

    }
    serial_intput_state->setText("input state:Right!");
    serial_write(serial_send_buf);
}
void  MainWindow::slot_serial_clock()
{
    //串口接收超时处理槽函数。
   // qDebug()<<"serial timeout";

}
void MainWindow::slot_create_set()
{
        qtset_form =new qtset();

}
